package com.xyb.config.exception;

import com.xyb.entity.Result;
import com.xyb.entity.StatusCode;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * 全局异常处理器
 */
@ControllerAdvice
@Slf4j
public class GlobalException {
    private int[] codes = new int[]{10000, 10001, 10002, 10003, 10004, 10005, 10006, 10010, 10011, 10020};

    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Result handler(HttpServletRequest request, HttpServletResponse response, Exception e) {
        // 出现异常给前台返回 500,这个是 Http 的状态码
        response.setStatus(500);
        /**
         * 自定义结果集
         */
        Result result = new Result<>();
        result.setFlag(false);

        log.info(e.getMessage());

        /**
         * 如果异常是业务异常,手动封装
         */
        if (e instanceof MyException) {
            MyException myException = (MyException) e;
            result.setMsg(((MyException) e).getMsg());

            int code = ((MyException) e).getCode();
            for (int i = 0; i < codes.length; i++) {
                if (code == codes[i]) {
                    response.setStatus(200);
                }
            }
            boolean flag = false; //状态码是否存在标识
            //如果code存在就用已经设置的状态码,不存在就设为 50000
            StatusCode[] codes = StatusCode.values();
            int length = codes.length;
            for (int i = 0; i < length; i++) {
                int tmpCode = codes[i].getCode();
                if (tmpCode == code) {
                    flag = true;
                    code = tmpCode;
                    break;
                }
            }
            code = flag ? code : StatusCode.UNDEFINED_ERROR.getCode();
            result.setCode(code);
            return result;
        }

        /**
         * 数据校验异常
         */
        if (e instanceof MethodArgumentNotValidException) {
            BindingResult br = ((MethodArgumentNotValidException) e).getBindingResult();
            String tipMsg = "";
            if (br.hasErrors()) {
                StringBuilder sb = new StringBuilder();
                List<ObjectError> errors = br.getAllErrors();
                //多个数据校验不匹配
                for (int i = 0; i < errors.size(); i++) {
                    sb.append(i + 1).append(":").append(errors.get(i).getDefaultMessage()).append(";  ");
                }
                tipMsg = sb.toString();
                tipMsg = tipMsg.substring(0, tipMsg.length() - 2);
            }
            result.setMsg(StatusCode.DATA_VALIDATION_EXCEPTION.getMsg() + ": " + tipMsg);
            result.setCode(StatusCode.DATA_VALIDATION_EXCEPTION.getCode());
            return result;
        }

        /**
         * 没有请求体
         */
        if (e instanceof HttpMessageNotReadableException) {
            result.setMsg(StatusCode.REQUEST_BODY_EXCEPTION.getMsg());
            result.setCode(StatusCode.REQUEST_BODY_EXCEPTION.getCode());
            return result;
        }

        /**
         * HTTP 请求类型异常
         */
        if (e instanceof HttpRequestMethodNotSupportedException) {
            result.setMsg(StatusCode.REQUEST_METHOD_EXCEPTION.getMsg() + ": " + e.getLocalizedMessage());
            result.setCode(StatusCode.REQUEST_METHOD_EXCEPTION.getCode());
            return result;
        }

        /**
         * 空指针异常
         */
        if (e instanceof NullPointerException) {
            result.setMsg(StatusCode.NULL_POINTER_EXCEPTION.getMsg() + ": " + e.getLocalizedMessage());
            result.setCode(StatusCode.NULL_POINTER_EXCEPTION.getCode());
            return result;
        }

        /**
         * token过期异常
         */
        if (e instanceof ExpiredJwtException) {
            result.setMsg(StatusCode.TOKEN_EXPIRED_EXCEPTION.getMsg() + ": " + e.getLocalizedMessage());
            result.setCode(StatusCode.TOKEN_EXPIRED_EXCEPTION.getCode());
            return result;
        }

        /**
         * 数组越界异常
         */

        /**
         * 如果是其他异常,默认参数
         */
        result.setMsg(StatusCode.UNDEFINED_ERROR.getMsg() + ": " + e.getClass().toString() + ": " + e.getMessage());
        result.setCode(StatusCode.UNDEFINED_ERROR.getCode());
        return result;
    }
}
